// START WRAPPER: The YUI.add wrapper is added by the build system, when you use YUI Builder to build your component from the raw source in this file
 YUI.add("bing-box-widget", function(Y) {

    /* Any frequently used shortcuts, strings and constants WidgetPostionAlign*/
    var Lang = Y.Lang,
    	WidgetStdMod = Y.WidgetStdMod;
    
    var StandardModule = Y.Base.create("standardModule", Y.Widget, [Y.WidgetPosition,Y.WidgetPositionAlign]);

    /* BingBoxWidget class constructor */
    function BingBoxWidget(config) {
        BingBoxWidget.superclass.constructor.apply(this, arguments);
    }

    /* 
     * Required NAME static field, to identify the Widget class and 
     * used as an event prefix, to generate class names etc. (set to the 
     * class name in camel case). 
     */
    BingBoxWidget.NAME = "BingBoxWidget";

    /*
     * The attribute configuration for the widget. This defines the core user facing state of the widget
     */
    BingBoxWidget.ATTRS = {
    	pairBox : {
    		value : null
    	},
    	zIndex : {
    		value : 0
    	},
        attrA : {
            value: "A"                     // The default value for attrA, used if the user does not set a value during construction.

            /*
            , valueFn: "_defAttrAVal"      // Can be used as a substitute for "value", when you need access to "this" to set the default value.
             
            , setter: "_setAttrA"          // Used to normalize attrA's value while during set. Refers to a prototype method, to make customization easier
            , getter: "_getAttrA"          // Used to normalize attrA's value while during get. Refers to a prototype method, to make customization easier
            , validator: "_validateAttrA"  // Used to validate attrA's value before updating it. Refers to a prototype method, to make customization easier

            , readOnly: true               // Cannot be set by the end user. Can be set by the component developer at any time, using _set
            , writeOnce: true              // Can only be set once by the end user (usually during construction). Can be set by the component developer at any time, using _set
            
            , lazyAdd: false               // Add (configure) the attribute during initialization. 
            
                                           // You only need to set lazyAdd to false if your attribute is
                                           // setting some other state in your setter which needs to be set during initialization 
                                           // (not generally recommended - the setter should be used for normalization. 
                                           // You should use listeners to update alternate state). 

            , broadcast: 1                 // Whether the attribute change event should be broadcast or not.
            */
        }
        
        // ... attrB, attrC, attrD ... attribute configurations. 

        // Can also include attributes for the super class if you want to override or add configuration parameters
    };

    /* 
     * The HTML_PARSER static constant is used if the Widget supports progressive enhancement, and is
     * used to populate the configuration for the BingBoxWidget instance from markup already on the page.
     */
    BingBoxWidget.HTML_PARSER = {

        attrA: function (srcNode) {
            // If progressive enhancement is to be supported, return the value of "attrA" based on the contents of the srcNode
        }

    };
    
    BingBoxWidget.ARTILE_TEMPLATE = '<div>{title}</div>';

    /* Templates for any markup the widget uses. Usually includes {} tokens, which are replaced through Y.substitute */
    BingBoxWidget.MYNODE_TEMPLATE = "<div id={mynodeid}></div>";

    /* BingBoxWidget extends the base Widget class */
    Y.extend(BingBoxWidget, StandardModule, {

        initializer: function() {
            /*
             * initializer is part of the lifecycle introduced by 
             * the Base class. It is invoked during construction,
             * and can be used to setup instance specific state or publish events which
             * require special configuration (if they don't need custom configuration, 
             * events are published lazily only if there are subscribers).
             *
             * It does not need to invoke the superclass initializer. 
             * init() will call initializer() for all classes in the hierarchy.
             */
        	this.timmer = null;
        	var viewPort = Y.one(document).get('viewportRegion');
        	var x1 = viewPort.left + 150,
        		wx = viewPort.width - 300,
        		y1 = viewPort.top + 100,
        		wy = viewPort.height - 200,
        		rx = Math.random(),
        		ry = Math.random();
        	
        	this.set('xy',[x1 + Math.round(wx*rx),y1 + Math.round(wy*ry)]);
        	this.get('boundingBox').setStyle('zIndex',this.get('zIndex'));
        },

        destructor : function() {
            /*
             * destructor is part of the lifecycle introduced by 
             * the Widget class. It is invoked during destruction,
             * and can be used to cleanup instance specific state.
             *
             * Anything under the boundingBox will be cleaned up by the Widget base class
             * We only need to clean up nodes/events attached outside of the bounding Box
             *
             * It does not need to invoke the superclass destructor. 
             * destroy() will call initializer() for all classes in the hierarchy.
             */
        	this._bingBoxEnterListener.detach();
        	this._bingBoxleaveListener.detach();
        	this._bingBoxMouseDelayListener.detach();
        	this._bintBoxMousemoveListener.detach();

        	this._bingBoxEnterListener = null;
        	this._bingBoxleaveListener = null;
        	this._bingBoxMouseDelayListener = null;
        	this._bintBoxMousemoveListener = null;
        	this.get('pairBox').destroy();
        },
        
        renderUI : function() {
            /*
             * renderUI is part of the lifecycle introduced by the
             * Widget class. Widget's renderer method invokes:
             *
             *     renderUI()
             *     bindUI()
             *     syncUI()
             *
             * renderUI is intended to be used by the Widget subclass
             * to create or insert new elements into the DOM. 
             */
        	var contentBox = this.get('contentBox'),
        		largeBox = this.get('pairBox'),
        		whiteDiv = Y.Node.create('<div></div>');
        		contentBox.appendChild(whiteDiv);
        		//初始状态
        		this.boxEntered = false;
        		this.boxHidden = false;
        },

        bindUI : function() {
            /*
             * bindUI is intended to be used by the Widget subclass 
             * to bind any event listeners which will drive the Widget UI.
             * 
             * It will generally bind event listeners for attribute change
             * events, to update the state of the rendered UI in response 
             * to attribute value changes, and also attach any DOM events,
             * to activate the UI.
             */
        	var boundingBox = this.get('boundingBox'); 
        	boundingBox.on('hover',this._mouseenter,this._mouseleave,this);
        	
        	if(Y.mouseMoveDelay){
        		;
        	}else{
        		Y.mouseMoveDelay = new Y.M3958.MouseMoveDelay({delay:0.8});
        	}
        	this._bingBoxMouseDelayListener = Y.mouseMoveDelay.on('mouseNotMove',function(e){
        		if(this.boxEntered || this.get('pairBox').get('boxEntered')){
        			;
        		}else{
       				this.fadeOut();
        		}
        	},this);
        	
        	this._bintBoxMousemoveListener = Y.one(document).on('mousemove',function(e){
        		if(this.boxHidden && !this.otherBoxEntered){
        			this.fadeIn();
        		}
        	},this);
        	
        	this._bingBoxEnterListener = Y.on('bingBox:enter',function(e){
        		if(e.boxId == boundingBox.get('id')){
        			this.otherBoxEntered = false;
        		}else{
        			this.otherBoxEntered = true;
        			this.boxHidden = true;
        			this.hide();
        		}
        	},this);
        	
        	this._bingBoxleaveListener = Y.on('bingBox:leave',function(e){
        		this.otherBoxEntered = false;
        	},this);
        },

        syncUI : function() {
            /*
             * syncUI is intended to be used by the Widget subclass to
             * update the UI to reflect the initial state of the widget,
             * after renderUI. From there, the event listeners we bound above
             * will take over.
             */
//        	var articles = this.get('articles'),
//        		outThis = this;
//        	if(articles){
//            	var c = Y.Array.reduce(articles,'',function(prev,a){
//            		return prev +  Y.Lang.sub(BingBoxWidget.ARTILE_TEMPLATE,{title:a.gett('title')});
//            	});
//            	outThis.setStdModContent(WidgetStdMod.BODY,c,WidgetStdMod.REPLACE);
//        	}
            // this._uiSetAttrA(this.get("attrA"));
        },

        // Beyond this point is the BingBoxWidget specific application and rendering logic

        /* Attribute state supporting methods (see attribute config above) */
        fadeOut : function(){
        	if(this.boxHidden)return;
        	this.boxHidden = true;
        	var lb = this.get('contentBox');
        	lb.transition({
        		easing: 'ease-in',
        		opacity: {
        			duration: 0.5,
        			value: 0}
        	},Y.bind(function(){
        		this.hide();
        	},this));
        },
        
        fadeIn : function(){
        	if(!this.boxHidden)return;
        	this.boxHidden = false;
        	var lb = this.get('contentBox');
        	this.show();
        	lb.transition({
        		easing: 'ease-in',
        		opacity: {
        			duration: 0.5,
        			value: 0.4}
        	},Y.bind(function(){
        		;
        	},this));
        },
        
        _mouseenter : function(e){
        	if(this.otherBoxEntered)return;
        	this.boxEntered = true;
        	var largeBox = this.get('pairBox');
        	Y.fire('bingBox:enter',{boxId:this.get('boundingBox').get('id')});
        	if(this.largeBoxRendered){
        		;
        	}else{
        		Y.log('render large box');
        		var	a = Y.WidgetPositionAlign,
        			boundingBox = this.get('boundingBox');
        		this.largeBoxRendered = true;
        		
        		var vr = boundingBox.get('viewportRegion'),
        			vw = vr.width,
        			vh = vr.height,
        			bx = this.get('xy')[0],
        			by = this.get('xy')[1],
        			zy = 'L',sx='T',p;
        		//以小方盒为中心
        		if(bx > vw/2){
        			zy = 'R';
        		}
        		if(by > vh/2){
        			sx = 'B';
        		}
        		
        		if(sx == 'T'){//在上部
        			if(zy == 'L'){//在左边
        				p = [a.TL,a.TR];
        			}else{//在右边
        				p = [a.TR,a.TL];
        			}
        		}else{//在下部
        			if(zy == 'L'){//在左边
        				p = [a.BL,a.BR];
        			}else{//在右边
        				p = [a.BR,a.BL];
        			}
        		}

        		largeBox.render();
        		largeBox.set("align", {
        		    node: boundingBox,
        		    points: p
        		});
        	}
        	largeBox.fadeIn();
        },
        
        _mouseleave : function(e){
        	this.boxEntered = false;
        	Y.fire('bingBox:leave');
        	var largeBox = this.get('pairBox');
    		if(this.timmer){
    			return;
    		}else{
    			this.timmer = Y.later(150,this,function(e){
    				largeBox.fadeOut();
    				this.timmer.cancel();
    				this.timmer = null;
    			});
    		}
        },
        
        _defMyEventFn : function(e) {
            // The default behavior for the "myEvent" event.
        }
    });

    Y.namespace("M3958").BingBoxWidget = BingBoxWidget;

 }, "0.0.1", {requires:["base","widget","widget-position","widget-position-align", "substitute","array-extras","transition","event","mouse-move-delay"]});
// END WRAPPER